import * as Blockly from 'blockly/core';
import * as Mixly from 'mixly';

const { MJson } = Mixly;

const typeBlockCheckPos = (block) => {
    const parent = block.getSurroundParent();
    if (parent && [
        'block_tool_value_input',
        'block_tool_statement_input',
        'block_tool_dummy_input'
    ].includes(parent.type)) {
        return true;
    }
    return false;
}

const typeBlockDropdownItemCheckPos = (block) => {
    const parent = block.getSurroundParent();
    if (parent && ['block_tool_type_dropdown', 'block_tool_type_grid_dropdown'].includes(parent.type)) {
        return true;
    }
    return false;
}

const generators = {};

const Generator = Blockly.Arduino ?? Blockly.Python;

generators.block_tool_type_text = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    let obj = {
        block: [
            `.appendField("${VALUE}")`
        ],
        generator: []
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_text_input = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldTextInput("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_multiline_input = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldMultilineInput("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_label_input = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldLabel("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_number_slider = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const TYPE = this.getFieldValue('TYPE');
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    const MIN = this.getFieldValue('MIN');
    const MAX = this.getFieldValue('MAX');
    const P = this.getFieldValue('P');
    let obj = {
        block: [
            `.appendField(new Blockly.${TYPE}(${VALUE}, ${MIN}, ${MAX}, ${P}), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_angle = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldAngle(${VALUE}), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_date = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldDate("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_dropdown = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    let valueStr = Generator.statementToCode(this, 'VALUE') || '';
    if (!valueStr) {
        return '';
    }
    const NAME = this.getFieldValue('NAME');
    let valueList = [];
    let obj = {
        block: [],
        generator: []
    };
    try {
        valueStr = valueStr.replace(Generator.INDENT, '');
        valueStr = valueStr.replaceAll('\n' + Generator.INDENT, '\n');
    } catch (error) {
        console.log(error);
    }
    valueList = valueStr.split('\n');
    if (valueList.length) {
        valueList.pop();
    }
    const FILL = '\n            ';
    const FILL_TAB = '\n                ';
    obj.block.push(`.appendField(new Blockly.FieldDropdown([${FILL_TAB}${valueList.join(',' + FILL_TAB)}${FILL}]), "${NAME}")`);
    obj.generator.push(`var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`);
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_grid_dropdown = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    let valueStr = Generator.statementToCode(this, 'VALUE') || '';
    if (!valueStr) {
        return '';
    }
    const NAME = this.getFieldValue('NAME');
    let valueList = [];
    let obj = {
        block: [],
        generator: []
    };
    try {
        valueStr = valueStr.replace(Generator.INDENT, '');
        valueStr = valueStr.replaceAll('\n' + Generator.INDENT, '\n');
    } catch (error) {
        console.log(error);
    }
    valueList = valueStr.split('\n');
    const COL = this.getFieldValue('COL');
    if (valueList.length) {
        valueList.pop();
    }
    const FILL = '\n            ';
    const FILL_TAB = '\n                ';
    let config = `{${FILL_TAB}columns: ${COL}${FILL}}`;
    obj.block.push(`.appendField(new Blockly.FieldGridDropdown([${FILL_TAB}${valueList.join(',' + FILL_TAB)}${FILL}], undefined, ${config}), "${NAME}")`);
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_dropdown_text = function () {
    if (!typeBlockDropdownItemCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let code = `["${VALUE}", "${NAME}"]\n`;
    return code;
};

generators.block_tool_type_dropdown_image = function () {
    if (!typeBlockDropdownItemCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    const WIDTH = this.getFieldValue('WIDTH');
    const HEIGHT = this.getFieldValue('HEIGHT');
    const ALT = this.getFieldValue('ALT');
    let code = `[{"src": "${VALUE}", "width": ${WIDTH}, "height": ${HEIGHT}, "alt": "${ALT}"}, "${NAME}"]\n`;
    return code;
};

generators.block_tool_type_bitmap = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const NAME = this.getFieldValue('NAME');
    const WIDTH = this.getFieldValue('WIDTH');
    const HEIGHT = this.getFieldValue('HEIGHT');
    const FILL_COLOR = this.getFieldValue('FILL_COLOR');
    const EMPTY_COLOR = this.getFieldValue('EMPTY_COLOR');
    const BG_COLOR = this.getFieldValue('BG_COLOR');
    const FILL = '\n            ';
    const FILL_TAB = '\n                ';
    let lineList = [];
    for (let i = 0; i < HEIGHT; i++) {
        let colList = new Array(WIDTH).fill(0);
        lineList.push('[' + colList.join(', ') + ']');
    }
    let config = `{${FILL_TAB}filledColor: "${FILL_COLOR}",${FILL_TAB}emptyColor: "${EMPTY_COLOR}",${FILL_TAB}bgColor: "${BG_COLOR}"${FILL}}`;
    let obj = {
        block: [
            `.appendField(new Blockly.FieldBitmap([${FILL_TAB}${lineList.join(',' + FILL_TAB)}${FILL}], undefined, ${config}), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_checkbox = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldCheckbox("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_color = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldColour("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_color_hsv_sliders = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const NAME = this.getFieldValue('NAME');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldColourHsvSliders("${VALUE}"), "${NAME}")`
        ],
        generator: [
            `var FIELD_${NAME.toUpperCase()} = this.getFieldValue("${NAME}");`
        ]
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

generators.block_tool_type_image = function () {
    if (!typeBlockCheckPos(this)) {
        return '';
    }
    const VALUE = this.getFieldValue('VALUE');
    const WIDTH = this.getFieldValue('WIDTH');
    const HEIGHT = this.getFieldValue('HEIGHT');
    const ALT = this.getFieldValue('ALT');
    let obj = {
        block: [
            `.appendField(new Blockly.FieldImage("${VALUE}", ${WIDTH}, ${HEIGHT}, "${ALT}"))`
        ],
        generator: []
    };
    let code = (MJson.stringify(obj) ?? {}) + '\n';
    return code;
};

export default generators;